package com.example.data.factory.service.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.data.factory.common.Dto.*;
import com.example.data.factory.common.Exception.DuplicateDataException;
import com.example.data.factory.common.VO.SearchDictDetailVO;
import com.example.data.factory.common.common.StringConstant;
import com.example.data.factory.common.result.PageVO;
import com.example.data.factory.common.result.R;
import com.example.data.factory.common.util.CodeGeneratorUtil;
import com.example.data.factory.common.util.CommonUtil;
import com.example.data.factory.entity.entity.Dict;
import com.example.data.factory.entity.entity.DictData;
import com.example.data.factory.mapper.mapper.DictMapper;
import com.example.data.factory.service.service.DictDataService;
import com.example.data.factory.service.service.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 码表 服务实现类
 * </p>
 *
 * @author lhy
 * @since 2025-03-03
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
    @Resource
    private DictMapper dictMapper;
    @Autowired
    private DictDataService dictDataService;
    @Resource
    private CommonUtil commonUtil;

    @Override
    public R<Dict> search(SearchDictDto searchDictDto) {
        Page<Dict> page = new Page<> ( searchDictDto.getPageNumber (), searchDictDto.getPageSize () );
        LambdaQueryWrapper<Dict> wrapper = new LambdaQueryWrapper<Dict> ()
                .like ( StringUtils.isNotBlank ( searchDictDto.getDictName () ), Dict::getDictName, searchDictDto.getDictName () )
                .eq ( searchDictDto.getStatus () != null, Dict::getStatus, searchDictDto.getStatus () )
                .eq ( Dict::getDeleted, 0 );
        Page<Dict> page1 = this.page ( page, wrapper );
        if (page1.getRecords ().isEmpty ()) {
            return R.Failed ( StringConstant.DICTNOTEXICTS );
        }
        PageVO<Dict> pageVO = new PageVO<> ();
        BeanUtil.copyProperties ( page1, pageVO );
        return R.Success ( pageVO );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Dict> insert(InsertDictDto insertDictDto, HttpServletRequest request) {
        Dict dict = new Dict ();
        dict.setCreateTime ( LocalDateTime.now () );
        dict.setUpdateTime ( LocalDateTime.now () );
        BeanUtil.copyProperties ( insertDictDto, dict );

        // 获取码表中已有的所有码表信息，判断新增的码表名称是否同原有的名称重复，如果重复则返回名称重复
        List<Dict> list = this.list ();
        if (list.stream ().anyMatch ( data -> data.getDictName ().equals ( insertDictDto.getDictName () ) )) {
            return R.Failed ( StringConstant.DICTNAMEISUSE );
        }
        Integer integer = dictMapper.selectMaxId ();
        String dictCode = CodeGeneratorUtil.generateCode ( "MZB", integer ); // 确保正确调用了静态方法
        dict.setDictCode ( dictCode );
        String username = commonUtil.extractUsernameFromRequest ( request );
        dict.setCreateBy ( username );
        boolean saveResult = this.save ( dict );
        if (!saveResult) {
            return R.Failed ( StringConstant.INSERTFAILD );
        }
        // 插入Dict_data表
        List<@Valid InsertDictDataDto> dictDataDtos = insertDictDto.getDictDataDtos ();
        if (dictDataDtos == null || dictDataDtos.isEmpty () ||
                dictDataDtos.stream ().anyMatch ( dictDataDto -> dictDataDto.getDictValue () == null || dictDataDto.getDictValue ().trim ().isEmpty () || dictDataDto.getDictLabel () == null || dictDataDto.getDictLabel ().isEmpty () )) {
            return R.Failed ( "码表值不能为空" );
        }
        for (InsertDictDataDto dictDataDto : dictDataDtos) {
            DictData dictData = new DictData ();
            dictData.setUpdateTime ( LocalDateTime.now () );
            dictData.setCreateTime ( LocalDateTime.now () );
            BeanUtil.copyProperties ( dictDataDto, dictData );

            // 仅检查与同一DictId关联的DictData是否包含相同的dictLabel或dictValue
            List<DictData> existingDictDatas = dictDataService.list ( new LambdaQueryWrapper<DictData> ()
                    .eq ( DictData::getDictId, dict.getDictId () ) );
            if (existingDictDatas.stream ().anyMatch ( data ->
                    data.getDictLabel ().equals ( dictDataDto.getDictLabel () ) ||
                            data.getDictValue ().equals ( dictDataDto.getDictValue () ) )) {
                throw new DuplicateDataException ( "Dict_data中存在重复的标签或值" );
            }
            dictData.setDictId ( Long.valueOf ( dict.getDictId () ) );
            dictDataService.save ( dictData ); // 使用服务层的方法保存DictData
        }

        return R.Success ( StringConstant.INSERTSUCCESS );
    }
    public R<Dict> Update(UpdateDictDto updateDictDto) {
        // 查找要更新的原始记录
        Dict originalDict = this.getOne ( new LambdaQueryWrapper<Dict> ()
                .eq ( Dict::getDictCode, updateDictDto.getDictCode () ) );

        if (originalDict == null || !(originalDict.getStatus () == 0 || originalDict.getStatus () == 2)) {
            return R.Failed ( StringConstant.UPDATEERRO );
        }
        boolean nameExists = this.list ().stream ().anyMatch ( data ->
                data.getDictName ().equals ( updateDictDto.getDictName () ) &&
                        !data.getDictId ().equals ( originalDict.getDictId () )
        );
        if (nameExists) {
            return R.Failed ( StringConstant.DICTNAMEISUSE );
        }

        // 创建一个Dict实体，仅设置需要更新的字段
        Dict updatedDict = new Dict ();
        BeanUtil.copyProperties ( updateDictDto, updatedDict );
        updatedDict.setUpdateTime ( LocalDateTime.now () );

        // 更新主表信息
        this.update ( updatedDict, new LambdaUpdateWrapper<Dict> ().eq ( Dict::getDictId, originalDict.getDictId () ) );

        // 处理DictData表中的数据
        List<UpdateDictDataDto> updateDataDtos = updateDictDto.getUpdateDataDtos ();

        // 提取更新请求中的所有DictData值，并检查是否有重复
        Set<String> valueSet = new HashSet<> ();
        for (@Valid UpdateDictDataDto updateDataDto : updateDataDtos) {
            if (!valueSet.add ( updateDataDto.getDictValue () ) ||
                    !valueSet.add ( updateDataDto.getDictLabel () )) {
                return R.Failed ( "数据重复" );
            }
        }
        //获取前端传过来的id
        Set<Integer> frontId = new HashSet<> ();
        for (UpdateDictDataDto dto : updateDataDtos) {
            if (dto.getDictDataId () != null) {
                frontId.add ( dto.getDictDataId () );
            }
        }
        // 获取当前DictData表中的所有与该Dict相关的记录
        List<DictData> existingDictDatas = dictDataService.list ( new LambdaQueryWrapper<DictData> ()
                .eq ( DictData::getDictId, originalDict.getDictId () ) );
        //找出需要删除的id
        Set<Integer> existsIds = existingDictDatas.stream ()
                .map ( DictData::getDictDataId )
                .collect ( Collectors.toSet () );
        Set<Integer> idsToDelete = new HashSet<> ( existsIds );
        idsToDelete.removeAll ( frontId );
        //删除多余的记录
        if (!idsToDelete.isEmpty ()) {
            boolean b = dictDataService.removeByIds ( idsToDelete );
            if (!b) {
                return R.Failed ( "删除多余的DictData失败" );
            }
        }
        //更新或者新增
        for (UpdateDictDataDto updateDataDto : updateDataDtos) {
            if (updateDataDto.getDictDataId () == null) {
                DictData dictData = new DictData ();
                BeanUtil.copyProperties ( updateDataDto, dictData );
                dictData.setUpdateTime ( LocalDateTime.now () );
                dictData.setCreateTime ( LocalDateTime.now () );
                dictData.setDictId ( Long.valueOf ( originalDict.getDictId () ) );
                boolean save = dictDataService.save ( dictData );
                if (!save) {
                    return R.Failed ( "新增DictData失败" );
                }
            } else { // 确保只处理有ID的更新请求
                // 查找对应的DictData记录
                Optional<DictData> matchingExistingData = existingDictDatas.stream ()
                        .filter ( existingData -> existingData.getDictDataId ().equals ( updateDataDto.getDictDataId () ) )
                        .findFirst ();
                if (matchingExistingData.isPresent ()) { // 找到匹配的记录
                    DictData existingData = matchingExistingData.get ();
                    // 更新现有记录
                    BeanUtil.copyProperties ( updateDataDto, existingData );
                    existingData.setUpdateTime ( LocalDateTime.now () );
                    boolean b = dictDataService.updateById ( existingData );
                    if (!b) {
                        return R.Failed ( "编号错误: 无法找到编号为" + updateDataDto.getDictDataId () + "的记录" );
                    }
                } else {
                    // 如果传入的更新请求中存在没有dictDataId的项，则直接返回失败
                    return R.Failed ( "请求中包含无效的更新数据，缺少dictDataId" );
                }
            }
        }
        return R.Success ( StringConstant.UPDATESUCCESS );
    }

    @Override
    public R<Dict> Delete(DeleteDictDto deleteDictDto) {
        // 获取要逻辑删除的Dict对象
        Dict byId = this.getById ( deleteDictDto.getDictId () );

// 检查Dict对象是否为空
        if (byId == null) {
            return R.Failed ( StringConstant.DICTNOTEXICTS );
        }

// 确认状态不为1且未被删除（假设status为1表示某种特殊状态）
        if (!(byId.getStatus () == 1) && byId.getDeleted () != 1) {
            // 设置deleted字段为1，表示逻辑删除
            byId.setDeleted ( (byte) 1 );
            // 更新数据库中的记录
            if (this.updateById ( byId )) {
                return R.Success ( StringConstant.UPDATESUCCESS );
            } else {
                return R.Failed ( StringConstant.UPDATEERRO );
            }
        } else {
            // 如果状态为1或已经被删除，则返回失败信息
            return R.Failed ( StringConstant.DICTNOTEXICTS );
        }
    }
    @Override
    public R<Dict> UpdateStatus(UpdateDictStatusDto updateDictStatusDto) {
        Dict dict =new Dict ();
        dict.setUpdateTime ( LocalDateTime.now () );
        BeanUtil.copyProperties (updateDictStatusDto,dict);
        LambdaUpdateWrapper<Dict> wrapper = new LambdaUpdateWrapper<Dict> ()
                .set (Dict::getStatus,updateDictStatusDto.getStatus ())
                .eq (Dict::getDictId,updateDictStatusDto.getDictId ());
         boolean update = this.update ( dict, wrapper );
         if (update) {
             return R.Success ( StringConstant.UPDATESUCCESS );
         } else {
             return R.Failed (StringConstant.UPDATEFAILED);
         }
    }

    @Override
    public R<Dict> searchdetail(SearchDictDetaildTO searchDictDetaildTO) {
        // 根据码表编号拿到码表数据
        Dict dict = this.getOne(new LambdaQueryWrapper<Dict>()
                .eq(Dict::getDictCode, searchDictDetaildTO.getDictCode())
                // 可能还需要确保只选择了未被删除的数据
                .eq(Dict::getDeleted, 0));
        if (dict == null) {
            // 处理找不到对应码表的情况
            throw new RuntimeException("未找到对应的码表");
        }

        // 得到该码表对应的编号
        Integer dictId = dict.getDictId();
        // 根据dictId寻找码表值
        // 假设有一个DictValue类用于存储码表值信息，并且有一个相应的Mapper或Service用于操作DictData实体
        List<DictData> dictValues = dictDataService.list(new LambdaQueryWrapper<DictData>()
                .eq(DictData::getDictId, dictId));
        if (dictValues == null || dictValues.isEmpty()) {
            // 处理没有找到任何码表值的情况
            throw new RuntimeException("未找到对应的码表值");
        }
        SearchDictDetailVO searchDictDetailVO = new SearchDictDetailVO ();
        searchDictDetailVO.setDictName (dict.getDictName ());
        searchDictDetailVO.setDictCode (dict.getDictCode ());
        searchDictDetailVO.setDescription ( dict.getDescription () );
        searchDictDetailVO.setDictData (dictValues);
        return R.Success (searchDictDetailVO);
    }

    @Override
    public R<Dict> updatestatusbatch(List<UpdateDictStatusDto> updateDictStatusDtos) {
        // 检查输入列表是否为空或null
        if (updateDictStatusDtos == null || updateDictStatusDtos.isEmpty()) {
            return R.Failed(StringConstant.DICTNOTEXISTS); // 修正了拼写错误
        }

        boolean allUpdatesSuccessful = true;

        for (UpdateDictStatusDto dto : updateDictStatusDtos) {
            // 查找是否存在未被删除的字典项
            Dict existingDict = this.getOne(new LambdaQueryWrapper<Dict>()
                    .eq(Dict::getDictId, dto.getDictId())
                    .eq(Dict::getDeleted, 0)); // 假设0代表未删除

            if (existingDict == null) {
                // 如果找不到未被删除的字典项，标记为失败但继续尝试更新其他记录
                allUpdatesSuccessful = false;
                continue;
            }
            Dict dict = new Dict ();
            dict.setUpdateTime ( LocalDateTime.now () );
            // 执行更新操作
            boolean updateResult = this.update(new LambdaUpdateWrapper<Dict>()
                    .set(Dict::getStatus, dto.getStatus())
                    .eq(Dict::getDictId, dto.getDictId()));

            if (!updateResult) {
                allUpdatesSuccessful = false;
            }
        }

        if (allUpdatesSuccessful) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        } else {
            return R.Failed ( "部分更新失败，可能是由于某些字典项已被删除或更新条件不匹配" );
        }
    }

    @Override
    public R<Dict> searchs() {
        List<Dict> list = this.list ( new LambdaQueryWrapper<Dict> ().eq ( Dict::getStatus, 1 ) );
        if (list == null || list.isEmpty ()) {
            return R.Failed ( "符合条件的数据不存在" );
        }
        return R.Success ( list );

    }
}
